package muhnes.sizoo.dal;

import com.googlecode.genericdao.dao.hibernate.GeneralDAOImpl;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.proxy.HibernateProxy;

/**
 * Clase generica que contiene los metodos mas generales de todas las entidades
 */
public abstract class GenericoDAO< T, ID extends Serializable > {
    
    private final GeneralDAOImpl dao ;
    protected SessionFactory fabricaSesion;
    
    public GenericoDAO () {
        dao = new GeneralDAOImpl();
    }
    
    public GenericoDAO ( SessionFactory fabricaSesion ) {
        dao = new GeneralDAOImpl();
        dao.setSessionFactory(fabricaSesion);
        this.fabricaSesion = fabricaSesion;
    }
    
    protected abstract Class<?> getClaseEntidad ();

    public void guardar ( T entidad ){
        dao.save(entidad);
        Session sesion = obtenerSesion();
        sesion.flush();
        System.out.println("XD");
    }

    public void guardarColeccion ( Collection< T > entidades ) {
        for( T entidad : entidades ) {
            dao.save(entidad);
        }
        Session sesion = obtenerSesion();
        sesion.flush();
    }

    public void actualizar ( T entidad ) {
        dao.save(entidad);
        Session sesion = obtenerSesion();
        sesion.flush();
    }

    public void actualizarColeccion ( Collection< T > entidades ) {
        for( T entidad : entidades ) {
            dao.save(entidad);
        }
        Session sesion = obtenerSesion();
        sesion.flush();
    }

    public void eliminar ( T entidad ) {
        dao.remove(entidad);
        Session sesion = obtenerSesion();
        sesion.flush();
    }

    public void eliminarColeccion ( Collection< T > entidades ) {
        for( T entidad : entidades ) {
            dao.remove(entidad);
        }
        Session sesion = obtenerSesion();
        sesion.flush();
    }

    public void eliminarPorId ( ID id ) {
        Class<?> clase = getClaseEntidad();
        dao.removeById(clase, id);
        Session sesion = obtenerSesion();
        sesion.flush();
    }

    public T buscarPorId ( ID id ) {
        Class<?> clase = getClaseEntidad();
        T entidad = (T)dao.find(clase, id);
        return entidad;
    }

    public List<T> buscarTodos () {
        Class<?> clase = getClaseEntidad();
        return (List<T>)dao.findAll(clase);
    }
    
    public void revertirCambios ( T entidad ) {
        dao.refresh( entidad );
    }
    
    public T removerProxy( T proxy ) {
        T entidad = proxy;
        if ( entidad != null && entidad instanceof HibernateProxy ) {
            Hibernate.initialize(entidad);
            entidad = (T)((HibernateProxy) entidad)
                    .getHibernateLazyInitializer()
                    .getImplementation();
        }

        return entidad;
    }
    
    public Session obtenerSesion () {
        return fabricaSesion.getCurrentSession();
    }
    
}
